import os
from django import forms
from django.conf import settings
from django.core.exceptions import ValidationError
from django.db import models
from .models import Ticket, MaintenanceRecord, TicketImage
from assets.models import Asset
# 延迟导入，避免循环导入问题
try:
    from spare_parts.models import SparePart
except ImportError:
    SparePart = None

# 使用标准FileInput，在模板中手动处理multiple属性

class TicketCreateForm(forms.ModelForm):
    """工单创建表单 - 支持多图片上传"""
    
    assets = forms.ModelMultipleChoiceField(
        queryset=Asset.objects.none(),
        widget=forms.SelectMultiple(attrs={'class': 'form-control'}),
        label='选择现有设备',
        required=False,
        help_text='从您的设备中选择（可多选，按住Ctrl选择多个）'
    )
    
    # 图片上传字段现在在模板中手动处理
    
    new_device_name = forms.CharField(
        max_length=100,
        required=False,
        widget=forms.TextInput(attrs={
            'class': 'form-control',
            'placeholder': '输入新设备名称'
        }),
        label='新设备名称'
    )
    
    new_device_model = forms.CharField(
        max_length=100,
        required=False,
        widget=forms.TextInput(attrs={
            'class': 'form-control',
            'placeholder': '输入设备型号'
        }),
        label='设备型号'
    )
    
    new_device_serial = forms.CharField(
        max_length=100,
        required=False,
        widget=forms.TextInput(attrs={
            'class': 'form-control',
            'placeholder': '输入序列号'
        }),
        label='序列号'
    )
    
    new_device_type = forms.ChoiceField(
        choices=Asset.TYPE_CHOICES,
        required=False,
        widget=forms.Select(attrs={'class': 'form-control'}),
        label='设备类型'
    )
    
    class Meta:
        model = Ticket
        fields = ['title', 'description', 'priority']
        widgets = {
            'title': forms.TextInput(attrs={
                'class': 'form-control',
                'placeholder': '请输入工单标题'
            }),
            'description': forms.Textarea(attrs={
                'class': 'form-control',
                'rows': 4,
                'placeholder': '请详细描述问题现象...'
            }),
            'priority': forms.Select(attrs={
                'class': 'form-control'
            }),
        }
        labels = {
            'title': '工单标题',
            'description': '问题描述', 
            'priority': '优先级',
        }

    def __init__(self, *args, **kwargs):
        user = kwargs.pop('user', None)
        super().__init__(*args, **kwargs)
        
        # 保存用户引用
        self.user = user
        
        # 只显示当前用户的正常状态设备
        if user:
            self.fields['assets'].queryset = Asset.objects.filter(
                assigned_to=user, 
                status='active'  # 只选择正常状态的设备
            )
        
        # 在编辑模式下，预选已关联的设备
        if self.instance and self.instance.pk:
            self.fields['assets'].initial = self.instance.assets.all()
        
        # 设置必填字段
        self.fields['title'].required = True
        self.fields['description'].required = True
        
        # 设置设备类型默认值
        self.fields['new_device_type'].initial = 'other'
        
        # 在编辑模式下，添加删除图片的字段
        if self.instance and self.instance.pk:
            # 使用CharField避免Django的选项验证问题
            self.fields['delete_images'] = forms.CharField(
                required=False,
                widget=forms.HiddenInput(),
                initial=''
            )

    def clean(self):
        cleaned_data = super().clean()
        new_device_name = cleaned_data.get('new_device_name')
        new_device_model = cleaned_data.get('new_device_model')
        new_device_serial = cleaned_data.get('new_device_serial')
        
        # 检查是否部分填写了新设备信息
        new_device_fields = [new_device_name, new_device_model, new_device_serial]
        if any(new_device_fields) and not all(new_device_fields):
            raise forms.ValidationError("如果要添加新设备，请完整填写设备名称、型号和序列号")
        
        # 验证上传的图片
        images = self.files.getlist('images') if self.files else []
        
        if images:
            # 验证图片数量
            max_count = getattr(settings, 'MAX_IMAGE_COUNT', 10)
            if len(images) > max_count:
                raise ValidationError(f'最多只能上传{max_count}张图片')
            
            # 验证每张图片
            total_size = 0
            allowed_extensions = getattr(settings, 'ALLOWED_IMAGE_EXTENSIONS', ['.jpg', '.jpeg', '.png', '.gif'])
            max_image_size = getattr(settings, 'MAX_IMAGE_SIZE', 5 * 1024 * 1024)
            
            for i, image in enumerate(images):
                # 验证文件大小
                if image.size > max_image_size:
                    raise ValidationError(f'图片 "{image.name}" 大小超过限制 ({max_image_size // (1024*1024)}MB)')
                
                # 验证文件扩展名
                file_ext = os.path.splitext(image.name)[1].lower()
                if file_ext not in allowed_extensions:
                    raise ValidationError(f'图片 "{image.name}" 格式不支持，请使用: {", ".join(allowed_extensions)}')
                
                total_size += image.size
            
            # 验证总大小
            max_total_size = getattr(settings, 'MAX_TOTAL_SIZE', 50 * 1024 * 1024)
            if total_size > max_total_size:
                raise ValidationError(f'图片总大小超过限制 ({max_total_size // (1024*1024)}MB)')
        
        # 处理删除图片的验证 - 过滤掉无效的图片ID
        delete_images_str = cleaned_data.get('delete_images', '')
        if delete_images_str and self.instance and self.instance.pk:
            # 解析逗号分隔的图片ID字符串
            delete_image_ids = [img_id.strip() for img_id in delete_images_str.split(',') if img_id.strip()]
            # 获取当前有效的图片ID
            valid_image_ids = set(str(img.id) for img in self.instance.images.all())
            # 过滤掉无效的图片ID
            filtered_delete_images = [img_id for img_id in delete_image_ids if img_id in valid_image_ids]
            # 重新组合为逗号分隔的字符串
            cleaned_data['delete_images'] = ','.join(filtered_delete_images)
        
        return cleaned_data

    def save(self, commit=True):
        from django.db import transaction
        
        ticket = super().save(commit=False)
        
        if commit:
            with transaction.atomic():
                # 保存工单基本信息
                ticket.save()
                
                # 处理设备关联
                self._save_assets(ticket)
                
                # 处理图片删除
                self._delete_images(ticket)
                
                # 处理图片上传
                self._save_images(ticket)
        
        return ticket
    
    def _save_assets(self, ticket):
        """处理设备关联"""
        # 原有的设备处理逻辑
        new_device_name = self.cleaned_data.get('new_device_name')
        new_device_model = self.cleaned_data.get('new_device_model')
        new_device_serial = self.cleaned_data.get('new_device_serial')
        new_device_type = self.cleaned_data.get('new_device_type')
        
        if new_device_name and new_device_model and new_device_serial and self.user:
            new_asset = Asset.objects.create(
                name=new_device_name,
                model=new_device_model,
                serial_number=new_device_serial,
                asset_type=new_device_type,
                assigned_to=self.user,
                department=self.user.username,
                status='active'
            )
            ticket.assets.add(new_asset)
        
        # 添加选择的现有设备
        selected_assets = self.cleaned_data.get('assets', [])
        if selected_assets:
            ticket.assets.add(*selected_assets)
    
    def _delete_images(self, ticket):
        """删除标记为删除的图片"""
        delete_images_str = self.cleaned_data.get('delete_images', '')
        if delete_images_str:
            # 解析逗号分隔的图片ID字符串
            delete_image_ids = [img_id.strip() for img_id in delete_images_str.split(',') if img_id.strip()]
            if delete_image_ids:
                # 转换为整数列表
                delete_ids = [int(img_id) for img_id in delete_image_ids]
                # 删除图片记录和文件
                images_to_delete = TicketImage.objects.filter(id__in=delete_ids, ticket=ticket)
                for image in images_to_delete:
                    # 删除物理文件
                    if image.image:
                        image.image.delete(save=False)
                    # 删除数据库记录
                    image.delete()
    
    def _save_images(self, ticket):
        """批量保存图片"""
        # 调试信息：检查接收到的文件
        print(f"Form FILES keys: {list(self.files.keys()) if self.files else 'No files'}")
        
        images = self.files.getlist('images') if self.files else []
        print(f"Number of images to save: {len(images)}")
        
        # 获取当前最大的order值
        max_order = TicketImage.objects.filter(ticket=ticket).aggregate(models.Max('order'))['order__max'] or -1
        
        for i, image_file in enumerate(images):
            print(f"Saving image {i+1}: {image_file.name}")
            TicketImage.objects.create(
                ticket=ticket,
                image=image_file,
                order=max_order + i + 1,
                description=f'工单图片 {max_order + i + 2}'
            )
        
        print(f"Saved {len(images)} images for ticket {ticket.id}")

class MaintenanceRecordForm(forms.ModelForm):
    """维修记录表单 - 支持备件使用记录"""
    
    # 备件使用字段
    spare_part = forms.ModelChoiceField(
        queryset=SparePart.objects.none(),
        widget=forms.Select(attrs={'class': 'form-control'}),
        label='使用备件',
        required=False,
        help_text='选择使用的备件（可选）'
    )
    
    spare_part_quantity = forms.IntegerField(
        min_value=1,
        initial=1,
        widget=forms.NumberInput(attrs={
            'class': 'form-control',
            'placeholder': '请输入使用数量'
        }),
        label='使用数量',
        required=False,
        help_text='请输入整数数量'
    )
    
    class Meta:
        model = MaintenanceRecord
        fields = ['description', 'parts_used', 'hours_spent']
        widgets = {
            'description': forms.Textarea(attrs={
                'class': 'form-control',
                'rows': 4,
                'placeholder': '详细记录维修过程和步骤...'
            }),
            'parts_used': forms.TextInput(attrs={
                'class': 'form-control',
                'placeholder': '例如：内存条8GB x 2, 硬盘1TB...'
            }),
            'hours_spent': forms.NumberInput(attrs={
                'class': 'form-control',
                'step': '0.5',
                'min': '0',
                'placeholder': '0.5'
            }),
        }
        labels = {
            'description': '维修描述',
            'parts_used': '使用零件',
            'hours_spent': '耗时(小时)',
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['description'].required = True
        
        # 只显示正常状态的备件
        from spare_parts.models import SparePart
        self.fields['spare_part'].queryset = SparePart.objects.filter(status='active')
        
        # 移除隐藏样式，让数量输入框可见
        if 'style' in self.fields['spare_part_quantity'].widget.attrs:
            del self.fields['spare_part_quantity'].widget.attrs['style']
        
    def clean(self):
        cleaned_data = super().clean()
        spare_part = cleaned_data.get('spare_part')
        spare_part_quantity = cleaned_data.get('spare_part_quantity')
        
        # 备件使用是可选的，但如果选择了备件就必须填写数量
        if spare_part and not spare_part_quantity:
            raise forms.ValidationError("请填写备件使用数量")
        
        # 如果填写了数量但没有选择备件，清除数量字段
        if spare_part_quantity and not spare_part:
            cleaned_data['spare_part_quantity'] = None
            
        # 如果选择了备件和数量，验证库存
        if spare_part and spare_part_quantity:
            if spare_part_quantity > spare_part.current_stock:
                raise forms.ValidationError(
                    f"库存不足，当前库存：{spare_part.current_stock} {spare_part.unit}"
                )
        
        return cleaned_data

    def save(self, commit=True):
        record = super().save(commit=False)
        
        if commit:
            record.save()
            
            # 处理备件使用记录
            spare_part = self.cleaned_data.get('spare_part')
            spare_part_quantity = self.cleaned_data.get('spare_part_quantity')
            
            if spare_part and spare_part_quantity:
                from spare_parts.models import UsageRecord, InventoryRecord
                
                # 创建使用记录并关联到维修记录
                usage_record = UsageRecord.objects.create(
                    spare_part=spare_part,
                    quantity=spare_part_quantity,
                    used_by=record.technician,
                    purpose=f'维修记录：{record.description[:50]}...',
                    ticket=record.ticket,
                    maintenance_record=record  # 关联到当前维修记录
                )
                
                # 创建出库记录
                InventoryRecord.objects.create(
                    spare_part=spare_part,
                    operation_type='out',
                    quantity=spare_part_quantity,
                    operator=record.technician,
                    related_usage=usage_record,
                    notes=f'维修使用：{record.description[:50]}...'
                )
        
        return record


class TicketRegisterForm(forms.ModelForm):
    """工单登记签收表单 - 用于前台添加设备信息和图片上传"""
    
    class Meta:
        model = Ticket
        fields = []  # 空字段，因为我们只处理设备和图片
    
    assets = forms.ModelMultipleChoiceField(
        queryset=Asset.objects.all(),
        widget=forms.SelectMultiple(attrs={'class': 'form-control'}),
        label='选择现有设备',
        required=False,
        help_text='从现有设备中选择（可多选，按住Ctrl选择多个）'
    )
    
    new_device_name = forms.CharField(
        max_length=100,
        required=False,
        widget=forms.TextInput(attrs={
            'class': 'form-control',
            'placeholder': '输入新设备名称'
        }),
        label='新设备名称'
    )
    
    new_device_model = forms.CharField(
        max_length=100,
        required=False,
        widget=forms.TextInput(attrs={
            'class': 'form-control',
            'placeholder': '输入设备型号'
        }),
        label='设备型号'
    )
    
    new_device_serial = forms.CharField(
        max_length=100,
        required=False,
        widget=forms.TextInput(attrs={
            'class': 'form-control',
            'placeholder': '输入序列号'
        }),
        label='序列号'
    )
    
    new_device_type = forms.ChoiceField(
        choices=Asset.TYPE_CHOICES,
        required=False,
        widget=forms.Select(attrs={'class': 'form-control'}),
        label='设备类型'
    )
    
    def __init__(self, *args, **kwargs):
        ticket = kwargs.pop('ticket', None)
        super().__init__(*args, **kwargs)
        
        # 保存工单引用
        self.ticket = ticket
        
        # 只显示正常状态的设备
        self.fields['assets'].queryset = Asset.objects.filter(status='active')
        
        # 如果提供了工单，预选已关联的设备
        if ticket and ticket.assets.exists():
            self.fields['assets'].initial = ticket.assets.all()
        
        # 设置设备类型默认值
        self.fields['new_device_type'].initial = 'other'
        
        # 添加删除图片的字段（用于编辑模式）
        if ticket and ticket.pk:
            self.fields['delete_images'] = forms.CharField(
                required=False,
                widget=forms.HiddenInput(),
                initial=''
            )
        
    def clean(self):
        cleaned_data = super().clean()
        new_device_name = cleaned_data.get('new_device_name')
        new_device_model = cleaned_data.get('new_device_model')
        new_device_serial = cleaned_data.get('new_device_serial')
        
        # 检查是否部分填写了新设备信息
        new_device_fields = [new_device_name, new_device_model, new_device_serial]
        if any(new_device_fields) and not all(new_device_fields):
            raise forms.ValidationError("如果要添加新设备，请完整填写设备名称、型号和序列号")
        
        # 验证上传的图片
        images = self.files.getlist('images') if self.files else []
        
        if images:
            # 验证图片数量
            max_count = getattr(settings, 'MAX_IMAGE_COUNT', 10)
            if len(images) > max_count:
                raise ValidationError(f'最多只能上传{max_count}张图片')
            
            # 验证每张图片
            total_size = 0
            allowed_extensions = getattr(settings, 'ALLOWED_IMAGE_EXTENSIONS', ['.jpg', '.jpeg', '.png', '.gif'])
            max_image_size = getattr(settings, 'MAX_IMAGE_SIZE', 5 * 1024 * 1024)
            
            for i, image in enumerate(images):
                # 验证文件大小
                if image.size > max_image_size:
                    raise ValidationError(f'图片 "{image.name}" 大小超过限制 ({max_image_size // (1024*1024)}MB)')
                
                # 验证文件扩展名
                file_ext = os.path.splitext(image.name)[1].lower()
                if file_ext not in allowed_extensions:
                    raise ValidationError(f'图片 "{image.name}" 格式不支持，请使用: {", ".join(allowed_extensions)}')
                
                total_size += image.size
            
            # 验证总大小
            max_total_size = getattr(settings, 'MAX_TOTAL_SIZE', 50 * 1024 * 1024)
            if total_size > max_total_size:
                raise ValidationError(f'图片总大小超过限制 ({max_total_size // (1024*1024)}MB)')
        
        # 处理删除图片的验证 - 过滤掉无效的图片ID
        delete_images_str = cleaned_data.get('delete_images', '')
        if delete_images_str and self.ticket and self.ticket.pk:
            # 解析逗号分隔的图片ID字符串
            delete_image_ids = [img_id.strip() for img_id in delete_images_str.split(',') if img_id.strip()]
            # 获取当前有效的图片ID
            valid_image_ids = set(str(img.id) for img in self.ticket.images.all())
            # 过滤掉无效的图片ID
            filtered_delete_images = [img_id for img_id in delete_image_ids if img_id in valid_image_ids]
            # 重新组合为逗号分隔的字符串
            cleaned_data['delete_images'] = ','.join(filtered_delete_images)
        
        return cleaned_data

    def save(self, commit=True):
        from django.db import transaction
        
        # 保存工单基本信息（虽然我们主要处理设备和图片）
        ticket = super().save(commit=False)
        
        if commit:
            with transaction.atomic():
                # 保存工单（如果需要）
                if hasattr(ticket, 'pk') and ticket.pk:
                    ticket.save()
                
                # 处理设备关联
                self._save_assets(ticket)
                
                # 处理图片删除
                self._delete_images(ticket)
                
                # 处理图片上传
                self._save_images(ticket)
        
        return ticket
    
    def _save_assets(self, ticket):
        """处理设备关联"""
        # 原有的设备处理逻辑
        new_device_name = self.cleaned_data.get('new_device_name')
        new_device_model = self.cleaned_data.get('new_device_model')
        new_device_serial = self.cleaned_data.get('new_device_serial')
        new_device_type = self.cleaned_data.get('new_device_type')
        
        if new_device_name and new_device_model and new_device_serial:
            # 创建新设备并分配给工单创建者
            new_asset = Asset.objects.create(
                name=new_device_name,
                model=new_device_model,
                serial_number=new_device_serial,
                asset_type=new_device_type,
                assigned_to=ticket.created_by,
                department=ticket.created_by.username,
                status='active'
            )
            # 将新设备添加到工单
            ticket.assets.add(new_asset)
        
        # 添加选择的现有设备
        selected_assets = self.cleaned_data.get('assets', [])
        if selected_assets:
            ticket.assets.add(*selected_assets)
    
    def _delete_images(self, ticket):
        """删除标记为删除的图片"""
        delete_images_str = self.cleaned_data.get('delete_images', '')
        if delete_images_str and ticket and ticket.pk:
            # 解析逗号分隔的图片ID字符串
            delete_image_ids = [img_id.strip() for img_id in delete_images_str.split(',') if img_id.strip()]
            if delete_image_ids:
                # 转换为整数列表
                delete_ids = [int(img_id) for img_id in delete_image_ids]
                # 删除图片记录和文件
                images_to_delete = TicketImage.objects.filter(id__in=delete_ids, ticket=ticket)
                for image in images_to_delete:
                    # 删除物理文件
                    if image.image:
                        image.image.delete(save=False)
                    # 删除数据库记录
                    image.delete()
    
    def _save_images(self, ticket):
        """批量保存图片"""
        # 调试信息：检查接收到的文件
        print(f"Form FILES keys: {list(self.files.keys()) if self.files else 'No files'}")
        
        images = self.files.getlist('images') if self.files else []
        print(f"Number of images to save: {len(images)}")
        
        if images and ticket and ticket.pk:
            # 获取当前最大的order值
            max_order = TicketImage.objects.filter(ticket=ticket).aggregate(models.Max('order'))['order__max'] or -1
            
            for i, image_file in enumerate(images):
                print(f"Saving image {i+1}: {image_file.name}")
                TicketImage.objects.create(
                    ticket=ticket,
                    image=image_file,
                    order=max_order + i + 1,
                    description=f'登记签收图片 {max_order + i + 2}'
                )
            
            print(f"Saved {len(images)} images for ticket {ticket.id}")
